﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using HAUtil;

using DotSpatial.Topology;

namespace HA.Data
{
    [Serializable]
    public class LineFO : FeatureObject
    {
        public LineFO(string id, List<HCoordinate> coords, Coverage coverage)
            : base(id,coverage)
        {

            this._coords = coords;

            this._polyKey = id;

            this._barrier = new BCBarrier();

            //int nPeriods = this.Parent.ParentCM.Model.NPeriods;

            this._specifiedFlow = new BCSpecifiedFlow();


        }

        #region New

        double _innerLineAngle = 0;
        /// <summary>
        /// 内部线角度总和 正向计算 计算多边形时使用
        /// </summary>
        public double InnerLineAngle
        {
            get { return _innerLineAngle; }
            set { _innerLineAngle = value; }
        }


        public LineFO(string id, NodeFO vertexStart, NodeFO vertexEnd, List<HCoordinate> coords, Coverage coverage)
            : base(id,coverage)
        {
            _vertexStart = new LineNode(vertexStart);
            _vertexEnd = new LineNode(vertexEnd);

            this._coords = coords == null ? new List<HCoordinate>() : coords;


            this._barrier = new BCBarrier();


            //int nPeriods = this.Parent.ParentCM.Model.NPeriods;

            this._specifiedFlow = new BCSpecifiedFlow();
        }

        /// <summary>
        /// 该函数进行的是线更新时需要的 额外 操作 为打断线单独提供
        /// </summary>
        /// <param name="type"></param>
        /// <param name="breakLines"></param>
        public void UpdateForLineChanged(CollectionChangedType type, List<LineFO> breakLines,bool isAdd=true)
        {
            List<string> ids = new List<string>();
            this.UpdateForLineChanged(type, ref ids, breakLines,isAdd);
        }

        /// <summary>
        /// 该函数进行的是线更新时需要的 额外 操作
        /// </summary>
        public void UpdateForLineChanged(CollectionChangedType type,ref List<string> ids ,List<LineFO> breakLines = null,bool isAdd=true)
        {
            if (breakLines != null)  //属于线的打断操做
            {
                if (isAdd == true)
                {
                    //更新新生成的线的对应的多边形所组成的线的信息
                    //暂时先不写
                    for (int i = 0; i < this._relatedPolygonFO.Count; i++)
                    {
                        PolygonFO polygon = this._relatedPolygonFO[i];
                        LineAndDirection lineDir;

                        if ((lineDir = polygon.RelationLines.FirstOrDefault(h => h.Line.Id == this.Id)) != null)
                        {
                            //更改多边形中的线集合
                            if (lineDir.Direction == 1)
                            {
                                int pos = polygon.RelationLines.IndexOf(lineDir);

                                List<LineAndDirection> newAddLines = new List<LineAndDirection>();

                                for (int j = 0; j < breakLines.Count; j++)
                                {
                                    newAddLines.Add(new LineAndDirection(breakLines[j], 1));
                                }
                                polygon.RelationLines.InsertRange(pos + 1, newAddLines);
                            }
                            else
                            {
                                int pos = polygon.RelationLines.IndexOf(lineDir);

                                List<LineAndDirection> newAddLines = new List<LineAndDirection>();

                                for (int j = 0; j < breakLines.Count; j++)
                                {
                                    newAddLines.Add(new LineAndDirection(breakLines[j], -1));
                                }

                                newAddLines.Reverse();

                                polygon.RelationLines.InsertRange(pos, newAddLines);
                            }
                        }
                        //else
                        //{
                        //    bool isFind = false;
                        //    foreach (List<LineAndDirection> item in polygon.HoleRelationLines)
                        //    {
                        //        if ((lineDir = item.FirstOrDefault(h => h.Line.Id == this.Id)) != null)
                        //        {
                        //            isFind = true;

                        //            //更改多边形中的线集合
                        //            if (lineDir.Direction == 1)
                        //            {
                        //                int pos = item.IndexOf(lineDir);

                        //                List<LineAndDirection> newAddLines = new List<LineAndDirection>();

                        //                for (int j = 0; j < breakLines.Count; j++)
                        //                {
                        //                    newAddLines.Add(new LineAndDirection(breakLines[j], 1));
                        //                }

                        //                item.InsertRange(pos + 1, newAddLines);
                        //            }
                        //            else
                        //            {
                        //                int pos = item.IndexOf(lineDir);

                        //                List<LineAndDirection> newAddLines = new List<LineAndDirection>();

                        //                for (int j = 0; j < breakLines.Count; j++)
                        //                {
                        //                    newAddLines.Add(new LineAndDirection(breakLines[j], -1));
                        //                }

                        //                newAddLines.Reverse();

                        //                item.InsertRange(pos, newAddLines);
                        //            }

                        //            break;
                        //        }
                        //    }
                        //    if (!isFind)
                        //        throw new Exception("多边形线信息错误！");
                        //}

                        if (!ids.Contains(polygon.Id))
                            ids.Add(polygon.Id);

                        polygon.BuildPolygon();
                    }


                    //打断时新生成的节点对应的线信息在这里更新，刘加
                    NodeFO node = null;
                    LineFO breakline;
                    for (int i = 0; i < breakLines.Count; i++)
                    {
                        breakline = breakLines[i];
                        if (this.VertexEnd.Node.Equals(breakline.VertexStart.Node))
                        {
                            node = breakline.VertexStart.Node;
                            if (node.RelationLines.Contains(this) == false)
                            {
                                node.RelationLines.Add(this);
                            }
                            if (node.RelationLines.Contains(breakline) == false)
                            {
                                node.RelationLines.Add(breakline);
                            }

                        }
                        if (this.VertexStart.Node.Equals(breakline.VertexEnd.Node))
                        {
                            node = breakline.VertexEnd.Node;
                            if (node.RelationLines.Contains(this) == false)
                            {
                                node.RelationLines.Add(this);
                            }
                            if (node.RelationLines.Contains(breakline) == false)
                            {
                                node.RelationLines.Add(breakline);
                            }
                        }

                        //新生成的线对应的多边形信息
                        breakline.RelatedPolygonFO.AddRange(this.RelatedPolygonFO.ToArray());
                    }
                }
                else
                {
                    //两条线合并成一条线时，参数isAdd为false

                    if (breakLines.Count > 1) return;
                    if (breakLines.Count < 1) return;

                    LineFO line = breakLines[0]; //要删除的线

                    foreach (PolygonFO polygon in line.RelatedPolygonFO)
                    {
                        foreach (LineAndDirection temLine in polygon.RelationLines)
                        {
                            if (temLine.Line.Equals(line))
                            {
                                polygon.RelationLines.Remove(temLine);  //删除 线对应的多边形对这条线的 关联                                
                                break;
                            }
                        }
                    }

                    line.RelatedPolygonFO.Clear();

                }
                return;

            }
            else
            {
                switch (type)
                {
                    case CollectionChangedType.REMOVE: //删除线的操做

                        for (int i = this._relatedPolygonFO.Count - 1; i >= 0; i--)
                        {
                            if (!ids.Contains(_relatedPolygonFO[i].Id))
                                ids.Add(_relatedPolygonFO[i].Id);
                            _relatedPolygonFO[i].UpdateForPolygonFOChanged(CollectionChangedType.REMOVE);
                        }

                        //如果此线的两个端点只连接着这一条线，则要删除端点
                        for (int i = this.VertexStart.Node.RelationLines.Count - 1; i >= 0; i--)
                        {
                            if (this.VertexStart.Node.RelationLines[i].Id == this.Id)
                                this.VertexStart.Node.RelationLines.RemoveAt(i);
                        }
                        //this.VertexStart.Node.RelationLines.Remove(this);
                        if (this.VertexStart.Node.RelationLines.Count == 0)
                        {
                            if (!ids.Contains(this.VertexStart.Id))
                                ids.Add(this.VertexStart.Id);
                        }
                        if (this.VertexStart.Id != this.VertexEnd.Id) //起始点和结束点不同，免得删重了
                        {
                            for (int i = this.VertexEnd.Node.RelationLines.Count - 1; i >= 0; i--)
                            {
                                if (this.VertexEnd.Node.RelationLines[i].Id == this.Id)
                                    this.VertexEnd.Node.RelationLines.RemoveAt(i);
                            }
                            //this.VertexEnd.Node.RelationLines.Remove(this);
                            if (this.VertexEnd.Node.RelationLines.Count == 0)
                            {
                                if (!ids.Contains(VertexEnd.Id))
                                    ids.Add(VertexEnd.Id);
                            }
                        }



                        break;
                    case CollectionChangedType.MOVE:

                        for (int i = this.RelatedPolygonFO.Count - 1; i >= 0; i--)
                        {

                            PolygonFO polygon = i >= this.RelatedPolygonFO.Count ? this.RelatedPolygonFO[i = this.RelatedPolygonFO.Count - 1] : this.RelatedPolygonFO[i];
                            LineAndDirection lineDir;

                            if ((lineDir = polygon.RelationLines.FirstOrDefault(h => h.Line.Id == this.Id)) != null)
                                lineDir.Line = this;
                            else
                            {
                                bool isFind = false;
                                foreach (List<LineAndDirection> item in polygon.HoleRelationLines)
                                {
                                    if ((lineDir = item.FirstOrDefault(h => h.Line.Id == this.Id)) != null)
                                    {
                                        lineDir.Line = this;
                                        isFind = true;
                                        break;
                                    }
                                }
                                if (!isFind)
                                    throw new Exception("多边形线信息错误！");
                            }

                            if (!ids.Contains(polygon.Id))
                                ids.Add(polygon.Id);

                            polygon.BuildPolygon();
                        }

                        break;
                    default:
                        break;
                }

            }

           
        }

        private int _searchTime = 0;

        public int SearchTime
        {
            get { return _searchTime; }
            set { _searchTime = value; }
        }

        List<PolygonFO> _relatedPolygonFO = new List<PolygonFO>();
        /// <summary>
        /// 与该线相关的多边形 最多为两个最少为0个
        /// </summary>
        public List<PolygonFO> RelatedPolygonFO
        {
            get { return _relatedPolygonFO; }
            set { _relatedPolygonFO = value; }
        }


        LineNode _vertexStart;
        /// <summary>
        /// 线起点
        /// </summary>
        public LineNode VertexStart
        {
            get { return _vertexStart; }
            set { _vertexStart = value; }
        }

        LineNode _vertexEnd;
        /// <summary>
        /// 线终点
        /// </summary>
        public LineNode VertexEnd
        {
            get { return _vertexEnd; }
            set { _vertexEnd = value; }
        }


        /// <summary>
        /// 提供获取线坐标点方法
        /// </summary>
        /// <param name="direction">1表示正向从首到尾，-1表示反向从尾到手</param>
        /// <returns></returns>
        public List<HCoordinate> ToCoordinatesArray(int direction = 1)
        {
            if (direction != 1 && direction != -1)
            {
                throw new Exception("起始点无效!");
            }

            List<HCoordinate> coords = new List<HCoordinate>();

            coords.Add(_vertexStart.Node.Position);
            coords.AddRange(_coords);
            coords.Add(_vertexEnd.Node.Position);

            if (direction == 1)
            {
                return coords;
            }
            else
            {
                coords.Reverse();
                return coords;
            }
        }


        #endregion

        

        List<HCoordinate> _coords;
        /// <summary>
        /// 内部点 不包含首尾端点，可能为空
        /// 若要获得线点请使用ToCoordinatesArray方法
        /// </summary>
        public List<HCoordinate> Coords
        {
            get { return _coords; }
            set { _coords = value; }
        }

        string _polyKey;
        /// <summary>
        /// 多边形线面对应标志  仅针对闭合线,非闭合线将始终返回"";
        /// </summary>
        public string PolyKey
        {
            get
            {
                if (!_isEnclosed)
                    return "";
                return _polyKey;
            }
            //set
            //{
            //    if (_isEnclosed)
            //        _polyKey = value;
            //}
        }


        bool _isEnclosed = false;

        public bool IsEnclosed
        {
            get { return _isEnclosed; }
            set { _isEnclosed = value; }
        }


        //这里我们先假设这里是正常的线条，不会进行扩展

        //double _conductancePerL;

        //public double ConductancePerL
        //{
        //    get { return _conductancePerL; }
        //    set { _conductancePerL = value; }
        //}





        BCBarrier _barrier;

        public BCBarrier Barrier
        {
            get { return _barrier; }
            set { _barrier = value; }
        }


        BCSpecifiedFlow _specifiedFlow;

        public BCSpecifiedFlow SpecifiedFlow
        {
            get { return _specifiedFlow; }
            set { _specifiedFlow = value; }
        }


        int _currentDirection = 1;

        public int CurrentDirection
        {
            get { return _currentDirection; }
            set { _currentDirection = value; }
        }


        #region 公共方法


        /// <summary>
        /// 复制属性到
        /// </summary>
        /// <param name="line"></param>
        public void CopyPropertiesTo(LineFO line)
        {
            line._selectedSCType = this._selectedSCType;             

            line._river = (BCRiver)this._river.Clone();
            line._layerRange = (LayerRange)this._layerRange.Clone();
            line._specifiedHead = (BCSpecifiedHead)this._specifiedHead.Clone();

            line._drain = (BCDrain)this._drain.Clone();

            line._seepage = (BCSeepageFace)this._seepage.Clone();

            line._generalHead = (BCGeneralHead)this._generalHead.Clone();


            line._massLoading = (BCMassLoading)this._massLoading.Clone();
            line._specConc = (BCSpecConc)this._specConc.Clone();

            //关于新改的映射规则部分

            line._lstIJK = new List<ValueResult>();

            line._barrier = this._barrier;
            line._specifiedFlow = this._specifiedFlow;

            //对应的多边形信息写在UpdateForLineChanged方法内了
            //line.RelatedPolygonFO = this.RelatedPolygonFO;
            //line.CurrentDirection = this.CurrentDirection;


        }



        /// <summary>
        /// 在线上插入一个顶点（普通点）
        /// </summary>
        /// <param name="coor"></param>
        public int InsertVertex(HCoordinate coor)
        {
            //先判断是否与线上的已存在点重合
            for (int i = 0; i < this._coords.Count;i++ )
            {
                if (coor.X == this._coords[i].X && coor.Y == this._coords[i].Y)
                {
                    return i;
                }
            }

           
            List<HCoordinate> coordLst = this.ToCoordinatesArray(1);

            if ((coor.X == coordLst[0].X && coor.Y == coordLst[0].Y) || (coor.X == coordLst[coordLst.Count - 1].X && coor.Y == coordLst[coordLst.Count - 1].Y))
            {
                return -1;
            }

            int insertIndex = 0;

            for (int i = 0; i < coordLst.Count - 1; i++)
            {
                //快速判断分割点在线上哪两个点之间
                if (coor.X > Math.Max(coordLst[i].X, coordLst[i + 1].X) ||
                    coor.X < Math.Min(coordLst[i].X, coordLst[i + 1].X) ||
                    coor.Y > Math.Max(coordLst[i].Y, coordLst[i + 1].Y) ||
                    coor.Y < Math.Min(coordLst[i].Y, coordLst[i + 1].Y))
                {
                    continue;
                }

                //矢量叉积法判断分割点在当前线段的哪个方向
                double value = (coor.X - coordLst[i + 1].X) * (coordLst[i].Y - coordLst[i + 1].Y) - (coordLst[i].X - coordLst[i + 1].X) * (coor.Y - coordLst[i + 1].Y);

                if (value == 0 || Math.Abs(value) < 0.0000001) //叉积为0则在线上,后面的是防误差
                {
                    insertIndex = i;
                    break;
                }

            }

            this._coords.Insert(insertIndex, coor);

            return insertIndex;

        }

        /// <summary>
        /// 顶点转节点
        /// </summary>
        /// <param name="vertexIndex"></param>
        /// <param name="coverage"></param>
        /// <returns></returns>
        public LineFO VertexToNode(int vertexIndex, ref List<string> ids)
        {
            
            List<HCoordinate> coorLst1 = new List<HCoordinate>();
            List<HCoordinate> coorLst2 = new List<HCoordinate>();

            coorLst1.AddRange(this._coords.GetRange(0, vertexIndex));
            coorLst2.AddRange(this._coords.GetRange(vertexIndex + 1, this._coords.Count - vertexIndex - 1));

            NodeFO node = new NodeFO(this.Parent.GetNextNodeId(), this._coords[vertexIndex], this.Parent);

            double separateValue = 0;
            double value1 = this._vertexStart.Value;
            double value2 = this._vertexEnd.Value;

            double distance1 = 0;
            double distance2 = 0;

            if (coorLst1.Count > 0)
            {
                distance1 += Math.Sqrt((coorLst1[0].X - this._vertexStart.Node.Position.X) * (coorLst1[0].X - this._vertexStart.Node.Position.X) +
                    (coorLst1[0].Y - this._vertexStart.Node.Position.Y) * (coorLst1[0].Y - this._vertexStart.Node.Position.Y));
                distance1 += Math.Sqrt((coorLst1[coorLst1.Count - 1].X - node.Position.X) * (coorLst1[coorLst1.Count - 1].X - node.Position.X) +
                    (coorLst1[coorLst1.Count - 1].Y - node.Position.Y) * (coorLst1[coorLst1.Count - 1].Y - node.Position.Y));
                for (int i = 0; i < coorLst1.Count - 1; i++)
                {
                    distance1 += Math.Sqrt((coorLst1[i].X - coorLst1[i + 1].X) * (coorLst1[i].X - coorLst1[i + 1].X) +
                        (coorLst1[i].Y - coorLst1[i + 1].Y) * (coorLst1[i].Y - coorLst1[i + 1].Y));
                }
            }
            else
            {
                distance1 += Math.Sqrt((node.Position.X - this._vertexStart.Node.Position.X) * (node.Position.X - this._vertexStart.Node.Position.X) +
                    (node.Position.Y - this._vertexStart.Node.Position.Y) * (node.Position.Y - this._vertexStart.Node.Position.Y));
            }

            if (coorLst2.Count > 0)
            {
                distance2 += Math.Sqrt((coorLst2[0].X - node.Position.X) * (coorLst2[0].X - node.Position.X) +
                   (coorLst2[0].Y - node.Position.Y) * (coorLst2[0].Y - node.Position.Y));
                distance2 += Math.Sqrt((coorLst2[coorLst2.Count - 1].X - this._vertexEnd.Node.Position.X) * (coorLst2[coorLst2.Count - 1].X - this._vertexEnd.Node.Position.X) +
                    (coorLst2[coorLst2.Count - 1].Y - this._vertexEnd.Node.Position.Y) * (coorLst2[coorLst2.Count - 1].Y - this._vertexEnd.Node.Position.Y));
                for (int i = 0; i < coorLst2.Count - 1; i++)
                {
                    distance2 += Math.Sqrt((coorLst2[i].X - coorLst2[i + 1].X) * (coorLst2[i].X - coorLst2[i + 1].X) +
                        (coorLst2[i].Y - coorLst2[i + 1].Y) * (coorLst2[i].Y - coorLst2[i + 1].Y));
                }
            }
            else
            {
                distance2 = Math.Sqrt((node.Position.X - this._vertexEnd.Node.Position.X) * (node.Position.X - this._vertexEnd.Node.Position.X) +
                    (node.Position.Y - this._vertexEnd.Node.Position.Y) * (node.Position.Y - this._vertexEnd.Node.Position.Y));
            }

            separateValue = value1 + distance1 / (distance1 + distance2) * (value2 - value1);


            //分割出一条新线，需要更新几何信息的同时，更新对应的模型信息


            LineFO newLine = new LineFO(this.Parent.GetNextLineId(), node, this._vertexEnd.Node, coorLst2, this.Parent);
            newLine.VertexStart.Value = separateValue;
            newLine.VertexEnd.Value = this.VertexEnd.Value;
            this.VertexEnd.Node.RelationLines.Remove(this);

            //新线的属性
            this.CopyPropertiesTo(newLine);

            //更新对应的模型信息

            BCType bc=this.GetCurrentBCType ();
            if (bc != null)
            {
                //新线段所占比例
                double ratioLine = distance1 / (distance1 + distance2);
                //double ratioNewLine = 1 - ratioLine;

                //取得原有线条的bc类型与实际值
                if (bc is BCRiver)
                {
                    BCRiver river = bc as BCRiver;

                    //double sStage = river.StartStage;
                    //double eStage = river.EndStage;

                    //double sElevation = river.StartElevation;
                    //double eElevation = river.EndElevation;

                    BCRiver newRiver = newLine.GetCurrentBCType() as BCRiver;

                    List<int> timePeriods = new List<int>();

                    this.ComputeCuttedDatas(river.MultiStartStage, newRiver.MultiStartStage, river.MultiEndStage, ratioLine);
                    river.MultiEndStage = (BCDateDataCollection)newRiver.MultiStartStage.Clone();

                    this.ComputeCuttedDatas(river.MultiStratElevation, newRiver.MultiStratElevation, river.MultiendElevation, ratioLine);
                    river.MultiendElevation = (BCDateDataCollection)newRiver.MultiStratElevation.Clone();


                    //for (int i = 0; i < river.MultiStartStage.Count; i++)
                    //{
                    //    double sStage = river.MultiStartStage[i].Value;
                    //    double eStage = river.MultiEndStage[i].Value;

                    //    double sElevation = river.MultiStratElevation[i].Value;
                    //    double eElevation = river.MultiendElevation[i].Value;

                    //    newRiver.MultiStartStage[i].Value = sStage + (eStage - sStage) * ratioLine;
                    //    river.MultiEndStage[i].Value = newRiver.MultiStartStage[i].Value;

                    //    newRiver.MultiStratElevation[i].Value = sElevation + (eElevation - sElevation) * ratioLine;
                    //    river.MultiendElevation[i] = newRiver.MultiStratElevation[i];
                    //}

                    //newRiver.StartStage = sStage + (eStage - sStage) * ratioNewLine;
                    //river.EndStage = newRiver.StartStage;

                    //newRiver.StartElevation = sElevation + (eElevation - sElevation) * ratioNewLine;
                    //river.EndElevation = newRiver.StartElevation;
                }
                else if (bc is BCDrain)
                {
                    BCDrain river = bc as BCDrain;

                    //double sElevation = river.StartElevation;
                    //double eElevation = river.EndElevation;

                    BCDrain newRiver = newLine.GetCurrentBCType() as BCDrain;

                    this.ComputeCuttedDatas(river.MultiStartElevation, newRiver.MultiStartElevation, river.MultiEndElevation, ratioLine);
                    river.MultiEndElevation = (BCDateDataCollection)newRiver.MultiStartElevation.Clone();


                    //for (int i = 0; i < river.MultiElevation.Count; i++)
                    //{
                    //    double sElevation = river.MultiStartElevation[i].Value;
                    //    double eElevation = river.MultiEndElevation[i].Value;

                    //    newRiver.MultiStartElevation[i].Value = sElevation + (eElevation - sElevation) * ratioLine;
                    //    river.MultiEndElevation[i] = newRiver.MultiStartElevation[i];
                    //}

                    //newRiver.StartElevation = sElevation + (eElevation - sElevation) * ratioNewLine;
                    //river.EndElevation = newRiver.StartElevation;
                }
                else if (bc is BCGeneralHead)
                {
                    BCGeneralHead river = bc as BCGeneralHead;

                    //double sStage = river.StartHead;
                    //double eStage = river.EndHead;

                    BCGeneralHead newRiver = newLine.GetCurrentBCType() as BCGeneralHead;

                    this.ComputeCuttedDatas(river.MultiStartHead, newRiver.MultiStartHead, river.MultiEndHead, ratioLine);
                    river.MultiEndHead = (BCDateDataCollection)newRiver.MultiStartHead.Clone();


                    //for (int i = 0; i < river.MultiStartHead.Count; i++)
                    //{
                    //    double sStage = river.MultiStartHead[i].Value;
                    //    double eStage = river.MultiEndHead[i].Value;

                    //    newRiver.MultiStartHead[i].Value = sStage + (eStage - sStage) * ratioLine;
                    //    river.MultiEndHead[i] = newRiver.MultiStartHead[i];
                    //}

                    //newRiver.StartHead = sStage + (eStage - sStage) * ratioNewLine;
                    //river.EndHead = newRiver.StartHead;
                }
                else if (bc is BCSeepageFace)
                {
                    BCSeepageFace river = bc as BCSeepageFace;

                    //double sElevation = river.ElevOffSetStart;
                    //double eElevation = river.ElevOffSetEnd;

                    BCSeepageFace newRiver = newLine.GetCurrentBCType() as BCSeepageFace;

                    this.ComputeCuttedDatas(river.MultiElevOffSetStart, newRiver.MultiElevOffSetStart, river.MultiElevOffSetEnd, ratioLine);
                    river.MultiElevOffSetEnd = (BCDateDataCollection)newRiver.MultiElevOffSetStart.Clone();


                    //for (int i = 0; i < river.MultiElevOffSetStart.Count; i++)
                    //{
                    //    double sElevation = river.MultiElevOffSetStart[i].Value;
                    //    double eElevation = river.MultiElevOffSetEnd[i].Value;

                    //    newRiver.MultiElevOffSetStart[i].Value = sElevation + (eElevation - sElevation) * ratioLine;
                    //    river.MultiElevOffSetEnd[i] = newRiver.MultiElevOffSetStart[i];
                    //}

                    //newRiver.ElevOffSetStart = sElevation + (eElevation - sElevation) * ratioNewLine;
                    //river.ElevOffSetEnd = newRiver.ElevOffSetStart;
                }
                else if (bc is BCSpecifiedHead)
                {
                    BCSpecifiedHead river = bc as BCSpecifiedHead;

                    //double sStage = river.StageStart;
                    //double eStage = river.StageEnd;

                    BCSpecifiedHead newRiver = newLine.GetCurrentBCType() as BCSpecifiedHead;

                    this.ComputeCuttedDatas(river.MultiStageStart, newRiver.MultiStageStart, river.MultiStageEnd, ratioLine);
                    river.MultiStageEnd = (BCDateDataCollection)newRiver.MultiStageStart.Clone();

                    //for (int i = 0; i < river.MultiStageStart.Count; i++)
                    //{
                    //    double sStage = river.MultiStageStart[i].Value;
                    //    double eStage = river.MultiStageEnd[i].Value;

                    //    newRiver.MultiStageStart[i].Value = sStage + (eStage - sStage) * ratioLine;
                    //    river.MultiStageEnd[i] = newRiver.MultiStageStart[i];

                    //}

                    //newRiver.StageStart = sStage + (eStage - sStage) * ratioNewLine;
                    //river.StageEnd = newRiver.StageStart;
                }
            }

           

            //更新（主要是更新多边形信息）
            //this.UpdateForLineChanged(CollectionChangedType.ITEMEDITMOVE,newLine);

            //==================================================================//
            
            //修改本条线
            this._coords = coorLst1;
            this._vertexEnd = new LineNode(node, separateValue);
            this.VertexEnd.Node.RelationLines.Add(this);


            //还有本条线其它的属性需要改的

            return newLine;
        }

        /// <summary>
        /// 数据顺序为打断后的
        /// </summary>
        /// <param name="firstStart"></param>
        /// <param name="secStart"></param>
        /// <param name="secEnd"></param>
        /// <param name="ratioLine"></param>
        private void ComputeCuttedDatas(BCDateDataCollection firstStart,BCDateDataCollection secStart,BCDateDataCollection secEnd,double ratioLine)
        {
            secStart.ConstData = 0;
            secStart.BCDatas.Clear();

            if (firstStart.IsDataConst && secEnd.IsDataConst)
            {
                secStart.ConstData = firstStart.ConstData + (secEnd.ConstData - firstStart.ConstData) * ratioLine;
            }
            else if (firstStart.IsDataConst && !secEnd.IsDataConst)
            {
                secStart.BCDatas = ((BCDateDataCollection)secEnd.Clone()).BCDatas;
                for (int i = 0; i < secEnd.BCDatas.Count; i++)
                {
                    secStart.BCDatas[i].Value = firstStart.ConstData +(secEnd.BCDatas[i].Value - firstStart.ConstData) * ratioLine;
                }
            }
            else if (!firstStart.IsDataConst && secEnd.IsDataConst)
            {
                secStart.BCDatas = ((BCDateDataCollection)firstStart.Clone()).BCDatas;
                for (int i = 0; i < firstStart.BCDatas.Count; i++)
                {
                    secStart.BCDatas[i].Value = firstStart.ConstData + (secEnd.ConstData - firstStart.BCDatas[i].Value) * ratioLine;
                }
            }
            else //都非  常数
            {
                bool isTransOver = false;
                int firstNum = 0;
                int secNum = 0;
                double firstValue = 0;
                double secValue = 0;
                int currentTime = 1;
                while (!isTransOver)
                {
                    if (firstNum == firstStart.BCDatas.Count || secNum == secEnd.BCDatas.Count)
                    {
                        if (firstNum == firstStart.BCDatas.Count)
                        {
                            if (secNum == secEnd.BCDatas.Count)
                                break;
                            secStart.BCDatas.Add(new BCDateData(currentTime, secEnd.BCDatas[secNum].EndTime, secValue * ratioLine));
                            secNum++;
                            for (int i = secNum; i < secEnd.BCDatas.Count; i++)
                            {
                                secStart.BCDatas.Add(new BCDateData(secEnd.BCDatas[secNum].StartTime, secEnd.BCDatas[secNum].EndTime, secValue * ratioLine));
                            }
                        }
                        else
                        {
                            secStart.BCDatas.Add(new BCDateData(currentTime, firstStart.BCDatas[firstNum].EndTime, firstValue + (0 - firstValue) * ratioLine));
                            firstNum++;
                            for (int i = firstNum; i < firstStart.BCDatas.Count; i++)
                            {
                                secStart.BCDatas.Add(new BCDateData(firstStart.BCDatas[firstNum].StartTime, firstStart.BCDatas[firstNum].EndTime, firstValue + (0 - firstValue) * ratioLine));
                            }
                        }
                        break;
                    }

                    firstValue = firstStart.BCDatas[firstNum].Value;
                    secValue = secEnd.BCDatas[secNum].Value;

                    if (firstStart.BCDatas[firstNum].EndTime == secEnd.BCDatas[secNum].EndTime)
                    {
                        secStart.BCDatas.Add(new BCDateData(currentTime, firstStart.BCDatas[firstNum].EndTime, firstValue + (secValue - firstValue) * ratioLine));

                        currentTime = firstStart.BCDatas[firstNum].EndTime + 1;
                        firstNum++;
                        secNum++;
                    }
                    else if (firstStart.BCDatas[firstNum].EndTime > secEnd.BCDatas[secNum].EndTime)
                    {
                        secStart.BCDatas.Add(new BCDateData(currentTime, secEnd.BCDatas[secNum].EndTime, firstValue + (secValue - firstValue) * ratioLine));

                        currentTime = secEnd.BCDatas[secNum].EndTime + 1;
                        secNum++;
                    }
                    else
                    {
                        secStart.BCDatas.Add(new BCDateData(currentTime, firstStart.BCDatas[firstNum].EndTime, firstValue + (secValue - firstValue) * ratioLine));

                        currentTime = firstStart.BCDatas[firstNum].EndTime + 1;
                        firstNum++;
                    }

                }
            }
        }


        public List<LineFO> VertexToNode(List<int> indexLst)
        {
            for (int i=0;i<indexLst .Count ;i++)
            {
                indexLst[i] = indexLst[i] - 1;
            }

            //排序
            for (int i = 0; i < indexLst.Count - 1; i++)
            {
                for (int j = i + 1; j < indexLst.Count; j++)
                {
                    if (indexLst[j] > indexLst[i])
                    {
                        int tem = indexLst[i];
                        indexLst[i] = indexLst[j];
                        indexLst[j] = tem;
                    }
                }
            }

            List<LineFO> result = new List<LineFO>();

            for (int i = 0; i < indexLst.Count; i++)
            {
                List<string> ids = new List<string>();
                LineFO newLine = this.VertexToNode(indexLst[i], ref ids);
                result.Add(newLine);
            }

            result.Reverse();

            return result;
        }


        //付加的接口函数

        public bool IsStartNode(NodeFO node)
        {
            if (node.Id == this._vertexStart.Id)
            {
                return true;

            }
            else
            {
                return false;
            }
        }


        public bool IsEndNode(NodeFO node)
        {

            if (node.Id == this._vertexEnd.Id)
            {
                return true;

            }

            else
            {
                return false;
            }
        }

        #endregion


        #region 重写的方法



        public override double GetTotalLValue()
        {
            List<HCoordinate> realCoords=this.ToCoordinatesArray();


            double length = 0;

            double temp = 0;

            for (int i = 0; i < realCoords.Count - 1; i++)
            {
                temp = Math.Pow((realCoords[i + 1].Y - realCoords[i].Y), 2) + Math.Pow((realCoords[i + 1].X - realCoords[i].X), 2); ;


                length += Math.Sqrt(temp);


            }


            return length;



        }



        public override void ResetCoords(List<HCoordinate> coords)
        {
            this._coords.Clear();
            this._coords.AddRange(coords);


        }




        public override void MapToModFlow(List<double> stressPeriods, ModFlow.Domain.DomainLayer.ModFlowData mf, CoverageSetup setup)
        {
            base.MapToModFlow(stressPeriods,mf, setup);


            //List<int[]> ijk;
            //ijk = this.GetIJKList(mf.GridData.GetBoundGrid());

            //for (int i = 0; i < ijk.Count; i++)
            //{

            //}



        }





        




        public override object Clone()
        {
            LineFO ln = (LineFO)base.Clone();

            ln._relatedPolygonFO = new List<PolygonFO>();
            ln._relatedPolygonFO.AddRange(_relatedPolygonFO);

            ln._vertexStart = (LineNode)_vertexStart.Clone();
            ln._vertexEnd = (LineNode)_vertexEnd.Clone();

            ln._coords = new List<HCoordinate>();
            foreach (HCoordinate item in this._coords)
            {
                ln._coords.Add((HCoordinate)item.Clone());
            }
            ln._barrier = (BCBarrier)this._barrier.Clone();
            ln._specifiedFlow = (BCSpecifiedFlow)this._specifiedFlow.Clone();

            return ln;

        }

        //internal override void OnNPeriodsChanged(int nPeriods)
        //{
        //    base.OnNPeriodsChanged(nPeriods);

        //    this._specifiedFlow.NPeriods = nPeriods;
        //}


        /// <summary>
        /// 因外部调用问题 计算barrier位置信息不好扩展，
        /// 故将其计算方法写在该方法中
        /// 不足之处为增加计算时间，效率有些许下降。
        /// 保加
        /// </summary>
        /// <param name="polys"></param>
        /// <param name="ibound"></param>
        /// <param name="From"></param>
        /// <param name="To"></param>
        protected override void BuildIJKList(DotSpatial.Topology.Polygon[,] polys, List<int[,]> ibound, Polygon polyGridFrame, int From, int To)
        {

            this._lstIJK.Clear();

            ///当无需建立ijk时,点，线不需要考虑太多
            ///
            ///

            if (this._selectedSCType == MAPSCType.NONE)
            {
                return;

            }



            int nlayers = ibound.Count;

            List<HCoordinate> realCoords = this.ToCoordinatesArray();

            //转换gis通用算法后的坐标
            List<Coordinate> coords = new List<Coordinate>();

            foreach (HAUtil.HCoordinate hCoordinate in realCoords)
            {
                Coordinate c = new Coordinate(hCoordinate.X, hCoordinate.Y);
                coords.Add(c);

               
            }


            if (this._isEnclosed)
            {
                Coordinate c = new Coordinate(realCoords[0].X, realCoords[0].Y);

                coords.Add(c);

            }


            LineString ls = new LineString(coords);

            int nrows = polys.GetLength(0);

            int ncols = polys.GetLength(1);

            #region 只在barrier使用
            ///计算barrier位置信息使用==============================================================保加
            if (this._selectedSCType == MAPSCType.BARRIER)
            {
                //首先构建中心点连线
                LineString[,] centerTwoPointLines = new LineString[nrows, ncols * 2];
                for (int i = 0; i < nrows; i++)
                {
                    for (int j = 0; j < ncols; j++)
                    {
                        Coordinate centroid = new Coordinate(polys[i, j].Centroid.X, polys[i, j].Centroid.Y);
                        if (i != nrows - 1)
                        {
                            Coordinate cenrow1 = new Coordinate(polys[i + 1, j].Centroid.X, polys[i + 1, j].Centroid.Y);
                            centerTwoPointLines[i, j * 2] = new LineString(new List<Coordinate> { centroid, cenrow1 });
                        }
                        if (j != ncols - 1)
                        {
                            Coordinate cencol1 = new Coordinate(polys[i, j + 1].Centroid.X, polys[i, j + 1].Centroid.Y);
                            centerTwoPointLines[i, j * 2 + 1] = new LineString(new List<Coordinate> { centroid, cencol1 });
                        }
                    }
                }

                //ibound有效性信息
                bool[, ,] _iboundSigns = new bool[nlayers, nrows, ncols * 2];
                for (int i = 0; i < nlayers; i++)
                {
                    for (int j = 0; j < nrows; j++)
                    {
                        for (int k = 0; k < ncols; k++)
                        {
                            if (ibound[i][j, k] == 0)
                            {
                                _iboundSigns[i, j, k * 2] = false;
                                _iboundSigns[i, j, k * 2 + 1] = false;
                            }
                            else
                            {
                                if (k == ncols - 1 || ibound[i][j, k + 1] != 0)
                                {
                                    _iboundSigns[i, j, k * 2 + 1] = true;
                                }
                                if (j == nrows - 1 || ibound[i][j + 1, k] != 0)
                                {
                                    _iboundSigns[i, j, k * 2] = true;
                                }
                            }
                        }
                    }
                }

                //开始循环遍历求位置
                for (int i = 0; i < nrows; i++)
                {
                    for (int j = 0; j < ncols * 2; j++)
                    {
                        if (centerTwoPointLines[i, j] != null)
                            if (centerTwoPointLines[i, j].Intersects(ls))
                                for (int k = From - 1; k < To; k++)
                                {
                                    if (k < nlayers && k > -1)
                                    {
                                        if (_iboundSigns[k, i, j])
                                            if (j % 2 == 0)
                                                this._lstIJK.Add(new ValueResult(i + 1, j / 2 + 1, k + 1, 0, i + 2, j / 2 + 1));
                                            else
                                                this._lstIJK.Add(new ValueResult(i + 1, (j + 1) / 2, k + 1, 0, i + 1, (j + 3) / 2));
                                    }
                                }
                    }
                }

                return;
            }
            ///计算barrier信息完毕====================================================================
            ///

            #endregion


            //模版VR
            List<ValueResult> tempIJKlst = new List<ValueResult>();

            for (int i = 0; i < nrows; i++)
            {
                for (int j = 0; j < ncols; j++)
                {
                    if (polys[i, j].Intersects(ls))
                    {
                        //需要寻找相交的长度，以及相交的次数
                        IGeometry ig = polys[i, j].Intersection(ls);

                        ValueResult vr = new ValueResult(i + 1, j + 1, 0, ig.Length);

                        tempIJKlst.Add(vr);
                    }
                }
            }


            //模版寻找结束，当是应该按照线的绘制顺序，排序

            //循环本线条的所有子线段
            List<ValueResult> sortedVr = new List<ValueResult>();

            //当前长度
            double currentLength = 0;

            for (int i = 0; i < coords.Count - 1; i++)
            {

                LineString lsSegment = new LineString(new List<Coordinate>() { coords[i], coords[i + 1] });

                List<ValueResult> segVR = new List<ValueResult>();


                //取得所有当前线段相交的单元

                for (int j = 0; j < tempIJKlst.Count; j++)
                {
                    if (polys[tempIJKlst[j].I - 1, tempIJKlst[j].J - 1].Intersects(lsSegment))
                    {
                        segVR.Add(tempIJKlst[j]);
 
                    }

                }

                if (segVR.Count > 0)
                {
                    double startInvalidLength = 0, endInvalidLength = 0;
                    Point p = new Point(coords[i]);

                    foreach (ValueResult item in segVR)
                    {
                        item.TempValue = polys[item.I - 1, item.J - 1].Distance(p);

                    }

                    segVR.Sort(ijkSort);

                    var interSects = polyGridFrame.Shell.Intersection(lsSegment);

                    if (polyGridFrame.Contains(new Point(coords[i])))
                    {
                        if (polyGridFrame.Contains(new Point(coords[i + 1])))
                        {
                            //不需操作
                        }
                        else//后段无效
                        {
                            endInvalidLength = coords[i + 1].Distance(interSects.Coordinate);
                        }
                    }
                    else//前段无效
                    {
                        if (polyGridFrame.Contains(new Point(coords[i + 1])))//前段无效
                        {
                            startInvalidLength = coords[i].Distance(interSects.Coordinate);
                        }
                        else//同时后段也无效
                        {
                            startInvalidLength = coords[i].Distance(interSects.Coordinates[0]);
                            endInvalidLength = coords[i + 1].Distance(interSects.Coordinates[1]);
                        }
                    }
                    //首先加起始无效
                    currentLength += startInvalidLength;

                    foreach (ValueResult item in segVR)
                    {
                        double innerLength = polys[item.I - 1, item.J - 1].Intersection(lsSegment).Length;
                        currentLength += innerLength;
                        //currentLength += item.Value;

                        if (!sortedVr.Exists(h => h.I == item.I && h.J == item.J && h.K == item.K))
                        {
                            sortedVr.Add(item);

                            item.TempRef = coords[i + 1];
                            //开始计算对应的当前长度
                            item.LineCurrentTotalLength = currentLength - innerLength / 2;
                        }
                        else
                        {
                            if (ReferenceEquals(item.TempRef, coords[i]))
                            {
                                item.LineCurrentTotalLength += innerLength / 2;
                                item.TempRef = coords[i];
                            }
                        }
                    }
                    //然后加结尾无效
                    currentLength += endInvalidLength;
                }
                else
                {

                    //未相交任何元素的长度直接相加

                    currentLength += lsSegment.Length;
                }
            }

            ///依据模版重置排序后的数据
            for (int k = From - 1; k < To; k++)
            {
                ///当i在有效范围的时候,这里的i 对应的图层的索引
                if (k < nlayers && k > -1)
                {
                    foreach (var item in sortedVr)
                    {
                        //判断有效性
                        if (ibound[k][item.I - 1, item.J - 1] != 0)
                        {
                            this._lstIJK.Add(new ValueResult(item.I, item.J, k + 1, item.Value) { LineCurrentTotalLength = item.LineCurrentTotalLength });
                        }
                    }
                }
            }
        }


        protected static int ijkSort(ValueResult x, ValueResult y)
        {
            if (x == null)
            {
                if (y == null)
                {
                    // If x is null and y is null, they're
                    // equal. 
                    return 0;
                }
                else
                {
                    // If x is null and y is not null, y
                    // is greater. 
                    return -1;
                }
            }
            else
            {
                // If x is not null...
                //
                if (y == null)
                // ...and y is null, x is greater.
                {
                    return 1;
                }
                else
                {
                    // ...and y is not null, compare the 
                    // lengths of the two strings.
                    //
                    int retval = x.TempValue.CompareTo(y.TempValue);
                  

                    if (retval != 0)
                    {
                        // If the strings are not of equal length,
                        // the longer string is greater.
                        //
                        return retval;
                    }
                    else
                    {
                        // If the strings are of equal length,
                        // sort them with ordinary string comparison.
                        //
                        return 0;
                    }
                }
            }
 
        }


        protected internal override BCType GetCurrentBCType()
        {
            BCType bc = base.GetCurrentBCType();
            if (bc == null)
            {
                if (this._selectedSCType == MAPSCType.SPECIFIEDFLOW)
                {
                    bc = this._specifiedFlow;


                }

                if (this._selectedSCType == MAPSCType.BARRIER)
                {
                    bc = this._barrier;

                }

            }

            return bc;

        }

        #endregion




       

    }
}
